package com.brillilab.starter.controller.aio.topics;

import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.brillilab.common.entity.PageVo;
import com.brillilab.common.entity.ResponseVo;
import com.brillilab.domain.enums.account.IntegralTypeEnum;
import com.brillilab.domain.enums.common.BoolEnum;
import com.brillilab.domain.enums.topic.TopicStateEnum;
import com.brillilab.domain.po.account.IntegralRecord;
import com.brillilab.domain.po.lab.LabMember;
import com.brillilab.domain.po.topics.Topic;
import com.brillilab.domain.po.topics.TopicDirection;
import com.brillilab.domain.po.topics.TopicExperiment;
import com.brillilab.domain.po.topics.TopicMember;
import com.brillilab.domain.po.topics.TopicTarget;
import com.brillilab.domain.po.user.Users;
import com.brillilab.domain.vo.account.IntegralAddTipsVo;
import com.brillilab.domain.vo.experiments.ExperimentMethodListVo;
import com.brillilab.domain.vo.kit.KitInfoListVo;
import com.brillilab.domain.vo.kit.ReagentTypeVo;
import com.brillilab.domain.vo.method.MethodDetail;
import com.brillilab.domain.vo.method.MethodVersionListItem;
import com.brillilab.domain.vo.topics.ExperimentIconVo;
import com.brillilab.domain.vo.topics.NewMethodTypeVo;
import com.brillilab.domain.vo.topics.TopicExperimentListAddVo;
import com.brillilab.domain.vo.topics.TopicExperimentResultVo;
import com.brillilab.domain.vo.topics.TopicExperimentVo;
import com.brillilab.domain.vo.topics.TopicExperimentsVo;
import com.brillilab.domain.vo.topics.TopicTargetPlanDateListVo;
import com.brillilab.domain.vo.user.UserInfoVo;
import com.brillilab.service.core.experiments.IExperimentService;
import com.brillilab.service.core.kit.IKitService;
import com.brillilab.service.core.kit.IReagentTypeService;
import com.brillilab.service.core.lab.ILabMemberService;
import com.brillilab.service.core.topics.ITopicDirectionService;
import com.brillilab.service.core.topics.ITopicExperimentService;
import com.brillilab.service.core.topics.ITopicMemberService;
import com.brillilab.service.core.topics.ITopicService;
import com.brillilab.service.core.topics.ITopicTargetService;
import com.brillilab.service.core.user.IUsersService;
import com.brillilab.service.logic.account.UserAccountLogic;
import com.brillilab.service.logic.experiments.ExperimentLogic;
import com.brillilab.service.logic.method.MethodLogic;
import com.brillilab.service.logic.method.MethodTypeLogic;
import com.brillilab.service.logic.topics.TopicLogic;
import com.brillilab.service.logic.user.UsersLogic;
import com.brillilab.service.module.message.producer.MessageProducer;
import com.brillilab.service.module.message.template.impl.topic.TargetToOtherMemberTemp;
import com.brillilab.starter.constant.StarterConstant;

/**
 * 课题Controller
 * 
 * @author lj
 *
 */
@RestController
@RequestMapping("/api/topicExperiment")
public class TopicExperimentController {
	@Resource
	private UsersLogic usersLogic;
	@Resource
	private TopicLogic topicLogic;
	@Resource
	private ITopicDirectionService topicDirectionService;
	@Resource
	private ITopicExperimentService topicExperimentService;
	@Resource
	private IExperimentService experimentService;
	@Resource
	private MethodTypeLogic methodTypeLogic;
	@Resource
	private IKitService kitService;
	@Resource
	private ITopicService topicService;
	@Resource
	private ExperimentLogic experimentLogic;
	@Resource
	private MessageProducer messageProducer;
	@Resource
	private IUsersService usersService;
	@Resource
	private ITopicMemberService topicMemberService;
	@Resource
	private MethodLogic methodLogic;
	@Resource
	private ITopicTargetService topicTargetService;
	@Resource
	private ILabMemberService labMemberService;
	@Resource
	private UserAccountLogic userAccountLogic;
	@Resource
	private IReagentTypeService reagentTypeService;
	
	/**
	 * 获取实验流计划时间组
	 * 
	 * @return
	 */
	@GetMapping("/planDateList")
	public ResponseVo getTargetPlanDateList(@RequestParam Long topicTargetId,
			@RequestHeader(name = StarterConstant.TOKEN) String token) {
		topicTargeIsDelete(topicTargetId);
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		TopicTargetPlanDateListVo vo = topicLogic.getTargetPlanDateList(userInfo.getLabMemberId(), topicTargetId);
		return ResponseVo.success(vo);
	}
	
	/**
	 * 新建实验目标
	 * 
	 * @return
	 */
	@PostMapping("/add")
	public ResponseVo experimentAdd(@RequestBody TopicExperimentListAddVo addVo,
			@RequestHeader(name = StarterConstant.TOKEN) String token) {
		TopicMember topicMember= null;
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		Topic topic = topicService.selectById(addVo.getTopicId());
		boolean isPower = topicLogic.topicEditPower(topic, userInfo);
		if(!isPower) {
			topicMember= topicMemberService.getTopicMember(addVo.getTopicId(),userInfo.getLabMemberId());
			isPower = topicMember!=null;
		}
		Assert.isTrue(isPower, "你没有权限操作该课题");
		addVo.setLabId(userInfo.getLabId());
		if(topicMember!=null) {
			addVo.setExecutorId(topicMember.getLabMemberId());
		}else {
			addVo.setExecutorId(topic.getExecutorId());
		}
		topicLogic.topicExperimentAdd(addVo,userInfo);
		
		IntegralRecord integralRecord = userAccountLogic.addIntegral(userInfo, IntegralTypeEnum.TOPIC, addVo.getTopicId());
		IntegralAddTipsVo tipsVo = new IntegralAddTipsVo();
		if(integralRecord!=null) {
			tipsVo.setTntegralTips("恭喜您，完成新建课题");
		}
		return ResponseVo.success(tipsVo);
	}

	/**
	 * 删除/作废实验目标
	 * 
	 * @return
	 */
	@GetMapping("/delete")
	public ResponseVo experimentDelete(@RequestParam Long topicExperimentId,
			@RequestHeader(name = StarterConstant.TOKEN) String token) {
		
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		TopicExperiment topicExperiment = topicExperimentService.selectById(topicExperimentId);
		if(!topicExperiment.getExecutorId().equals(userInfo.getLabMemberId())) {
			Topic topic = topicService.selectById(topicExperiment.getTopicId());
			boolean isPower = topicLogic.topicEditPower(topic, userInfo);
			Assert.isTrue(isPower, "你没有权限操作该课题");
		}
		
		topicExperimentService.deleteById(topicExperiment);
		return ResponseVo.success();
	}
	
	/**
	 * 恢复实验目标
	 * 
	 * @return
	 */
	@GetMapping("/recovery")
	public ResponseVo experimentRecovery(@RequestParam Long topicExperimentId,
			@RequestHeader(name = StarterConstant.TOKEN) String token) {
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		TopicExperiment topicExperiment = topicExperimentService.selectById(topicExperimentId);
		if(!topicExperiment.getExecutorId().equals(userInfo.getLabMemberId())) {
			Topic topic = topicService.selectById(topicExperiment.getTopicId());
			boolean isPower = topicLogic.topicEditPower(topic, userInfo);
			Assert.isTrue(isPower, "你没有权限操作该课题");
		}
		
		topicExperimentService.recovery(topicExperimentId);
		return ResponseVo.success();
	}
	
	/**
	 * 课题实验执行人切换
	 * 
	 * @return
	 */
	@GetMapping("/executorEdit")
	public ResponseVo experExecutorEdit(@RequestParam Long topicExperimentId,
			@RequestParam Long executorId, @RequestHeader(name = StarterConstant.TOKEN) String token) {
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		TopicExperiment topicExperiment = topicExperimentService.selectById(topicExperimentId);
		if (!topicExperiment.getExecutorId().equals(executorId) ) {
			Topic topic = topicService.selectById(topicExperiment.getTopicId());
			boolean isPower = topicLogic.topicEditPower(topic, userInfo);
			Assert.isTrue(isPower, "你没有权限操作该课题");
			
			topicLogic.experExecutorEdit(topicExperimentId,executorId);
			
			if (!userInfo.getLabMemberId().equals(executorId)) {
				this.targetToOtherMemberTemp(topicExperiment.getLabId(), executorId, userInfo.getName(),
						topicExperiment.getMethodTypeName(), topicExperiment.getTopicId(), TopicStateEnum.UNDER_WAY.getValue(),topicExperiment.getTopicDirectionId(),topicExperiment.getTopicTargetId());
			}
		}
		return ResponseVo.success();
	}
	
	private void targetToOtherMemberTemp(Long labId, Long executorId, String operatorName, String targetName, Long referId, Integer topicState,Long topicDirectionId,Long topicTargetId) {
        Users user = usersService.selectUser(labId, executorId, null);
        TargetToOtherMemberTemp temp = new TargetToOtherMemberTemp(labId, user.getId(), executorId, referId, operatorName, targetName, topicState,topicDirectionId,topicTargetId);
        messageProducer.sendMessagePush(temp);
    }
	
	/**
	 * 获取实验目标列表
	 * 
	 * @return
	 */
	@Deprecated
	@GetMapping("/list")
	public ResponseVo experimentList(@RequestParam Long topicTargetId, Long targetGroupId,
			@RequestHeader(name = StarterConstant.TOKEN) String token) {
		topicTargeIsDelete(topicTargetId);
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		TopicExperimentsVo experimentsVo = topicLogic.getExperimentList(userInfo,topicTargetId, targetGroupId);
		return ResponseVo.success(experimentsVo.getVoList());
	}
	
	/**
	 * 获取实验目标列表(包含实验流名称和Figure)
	 * 
	 * @return
	 */
	@GetMapping("/listVo")
	public ResponseVo experimentListVo(@RequestParam Long topicTargetId, Long targetGroupId,
			@RequestHeader(name = StarterConstant.TOKEN) String token) {
		topicTargeIsDelete(topicTargetId);
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		TopicExperimentsVo experimentsVo = topicLogic.getExperimentList(userInfo,topicTargetId, targetGroupId);
		return ResponseVo.success(experimentsVo);
	}
	
	//校验实验流是否删除
	private void topicTargeIsDelete(Long topicTargetId) {
		TopicTarget target = topicTargetService.selectById(topicTargetId);
		Assert.isTrue(target!=null && BoolEnum.FALSE.getValue().equals(target.getIsDelete()), "实验流已被删除");
		TopicDirection direction = topicDirectionService.getById(target.getTopicDirectionId());
		Assert.isTrue(direction!=null && BoolEnum.FALSE.getValue().equals(direction.getIsDelete()), "研究内容已被删除");
		Topic topic = topicService.selectById(target.getTopicId());
		Assert.isTrue(topic!=null && BoolEnum.FALSE.getValue().equals(topic.getIsDelete()), "课题已被删除");
	}
	
	/**
	 * 获取课题实验日期切换的实验信息
	 * 
	 * @return
	 */
	@GetMapping("/info")
	public ResponseVo experimentInfo(@RequestParam Long experimentId,
			@RequestHeader(name = StarterConstant.TOKEN) String token) {
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		TopicExperimentVo vo = topicLogic.getExperimentInfo(userInfo,experimentId);
		return ResponseVo.success(vo);
	}
	
	/**
	 * 获取实验流中实验目标历史实验数据
	 * 
	 * @return
	 */
	@GetMapping("/history")
	public ResponseVo experimentHistory(@RequestParam Long topicExperimentId,
			@RequestHeader(name = StarterConstant.TOKEN) String token) {
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		List<TopicExperimentResultVo> historyList = topicLogic.getExperimentHistory(topicExperimentId);
		if(CollectionUtils.isNotEmpty(historyList)) {
			boolean isLeader = experimentLogic.isLeader(historyList.get(0).getExperimentId(), userInfo);
			if(isLeader) {
				for (TopicExperimentResultVo resultVo : historyList) {
					experimentService.experimentGuideSetting(resultVo.getExperimentId(), 2, 2);
				}
			}
		}
		return ResponseVo.success(historyList);
	}
	
	/**
	 * 获取实验流中实验目标历史实验Icon
	 * 
	 * @return
	 */
	@GetMapping("/experimentIcon")
	public ResponseVo experimentIcon(@RequestParam Long experimentId,
			@RequestHeader(name = StarterConstant.TOKEN) String token) {
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		List<ExperimentIconVo> historyList = topicLogic.experimentIcon(userInfo.getLabMemberId(), experimentId);
		return ResponseVo.success(historyList);
	}

	/**
	 * 新建课题-方法类型列表
	 * @author WuMengaho
	 * @param topicTargetId
	 * @param token
	 * @return
	 */
	@GetMapping("/methodTypeList")
	public ResponseVo methodTypeList(Long topicTargetId,@RequestHeader(name = StarterConstant.TOKEN) String token) {
		Assert.notNull(topicTargetId,"请求参数缺失!");
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		List<NewMethodTypeVo> methodTypeVos = methodTypeLogic.getTopicMethodTypeList(topicTargetId,userInfo);
		return ResponseVo.success(methodTypeVos);
	}

	/**
	 * 新建实验-常用方法类型
	 * @param topicTargetId
	 * @param token
	 * @return
	 */
	@GetMapping("/freqMethodTypes")
	public ResponseVo freqMethodTypes(Long topicTargetId,@RequestHeader(name = StarterConstant.TOKEN) String token){
		Assert.notNull(topicTargetId,"请求参数缺失!");
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		List<NewMethodTypeVo> methodTypeVos = methodTypeLogic.getTopicFreqMethodTypeList(topicTargetId,userInfo);
		return ResponseVo.success(methodTypeVos);
	}

	/**
	 * 新建实验-最常用方法类型
	 * @param topicTargetId
	 * @param token
	 * @return
	 */
	@GetMapping("/topFreqMethodTypes")
	public ResponseVo topFreqMethodTypes(Long topicTargetId,@RequestHeader(name = StarterConstant.TOKEN) String token){
		Assert.notNull(topicTargetId,"请求参数缺失!");
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		List<NewMethodTypeVo> methodTypeVos = methodTypeLogic.getTopTopicFreqMethodTypeList(topicTargetId,userInfo);
		return ResponseVo.success(methodTypeVos);
	}

	/**
	 * 搜索
	 *
	 * @param name
	 * @param topicTargetId
	 * @param token
	 * @return
	 */
	@RequestMapping(value="/methodTypeSearch", method=RequestMethod.GET)
	public ResponseVo methodTypeSearch(String name,Long topicTargetId, @RequestHeader(StarterConstant.TOKEN) String token){
		Assert.isTrue(StringUtils.isNotBlank(token),"请求参数缺失！");
		List<NewMethodTypeVo> methodTypes = methodTypeLogic.search(name,topicTargetId);
		return ResponseVo.success(methodTypes);
	}

	/**
	 * 新建课题-试剂列表
	 * @author WuMenghao
	 * @param token
	 * @return
	 */
	@GetMapping("/reagentList")
	public ResponseVo kitOfMethodList(Long topicTargetId,Long methodTypeId, String search,
									  Long reagentTypeId,Long topicExperimentId,
									  @RequestParam(defaultValue = "1") Integer  pageNum,
									  @RequestParam(defaultValue = "10")Integer pageSize,
									  @RequestHeader(name = StarterConstant.TOKEN) String token){
		Assert.notNull(topicTargetId,"请求参数缺失!");
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		PageVo<KitInfoListVo> kitList = kitService.selectMethodReagentList(topicTargetId,topicExperimentId,methodTypeId,reagentTypeId,search, userInfo.getLabId(),pageSize,pageNum);
		return ResponseVo.success(kitList);
	}

	/**
	 * 新建实验-全局试剂方法导入列表
	 * @author WuMenghao
	 * @param token
	 * @return
	 */
	@GetMapping("/reagentImportList")
	public ResponseVo kitOfImportList(Long topicTargetId,Long methodTypeId, String search,
									  Long reagentTypeId,Long topicExperimentId,
									  @RequestParam(defaultValue = "1") Integer  pageNum,
									  @RequestParam(defaultValue = "10")Integer pageSize,
									  @RequestHeader(name = StarterConstant.TOKEN) String token){
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		PageVo<KitInfoListVo> kitList = kitService.selectMethodReagentImportList(topicTargetId,topicExperimentId,methodTypeId,reagentTypeId,search, userInfo.getLabId(),pageSize,pageNum);
		return ResponseVo.success(kitList);
	}

	/**
	 * 新建课题-试剂类型列表
	 * @author WuMenghao
	 * @param token
	 * @return
	 */
	@GetMapping("/reagentTypeList")
	public ResponseVo reagentTypeOfMethodList(Long topicTargetId, @RequestHeader(name = StarterConstant.TOKEN) String token){
		Assert.notNull(topicTargetId,"请求参数缺失!");
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		TopicTarget topicTarget = topicTargetService.selectById(topicTargetId);
		Assert.notNull(topicTarget,"实验流不存在!");
		Topic topic = topicService.selectById(topicTarget.getTopicId());
		Assert.notNull(topic,"课题不存在!");
		List<ReagentTypeVo> list = reagentTypeService.getTopicReagentTypeList(topic.getExecutorId(),userInfo.getLabId());
		return ResponseVo.success(list);
	}

	/**
	 * 开始实验选择方法列表
	 *
	 * @return
	 */
	@GetMapping("/methodList")
	public ResponseVo methodList(Long methodTypeId,Long topicTargetId,Boolean exportCountAsc,Boolean successRateAsc,
								 @RequestHeader(name = StarterConstant.TOKEN) String token) {
		Assert.isTrue(methodTypeId!=null && topicTargetId!=null,"请求参数缺失!");
		List<ExperimentMethodListVo> methodList = topicLogic.getMethodList(topicTargetId,
				methodTypeId,exportCountAsc,successRateAsc);
		return ResponseVo.success(methodList);
	}

	/**
	 * 课题方法列表-方法历史版本
	 * @param methodId
	 * @param token
	 * @return
	 */
	@GetMapping("/versionList")
	public ResponseVo versionList(Long methodId,Long topicTargetId, @RequestHeader(value = StarterConstant.TOKEN) String token) {
		Assert.isTrue(methodId!=null && topicTargetId!=null,"请求参数缺失!");
		UserInfoVo user = usersLogic.getUserByToken(token);
		Assert.notNull(methodId, "参数缺失");
		TopicTarget topicTarget=topicTargetService.selectById(topicTargetId);
		Assert.notNull(topicTarget,"课题目标不存在!");
		Topic topic=topicService.selectById(topicTarget.getTopicId());
		Assert.notNull(topic,"课题不存!");
		LabMember labMember=labMemberService.selectById(topic.getExecutorId());
		Assert.notNull(labMember,"主执行人不是当前实验室成员!");
		UserInfoVo userInfo=usersLogic.getUserInfo(user.getLabId(),labMember.getUserId());
		List<MethodVersionListItem> methodList = topicLogic.getMethodVersionList(methodId,userInfo,topicTargetId);
		return ResponseVo.success(methodList);
	}

	/**
	 * 方法详情
	 *
	 * @return
	 */
	@GetMapping("/reagentMethodDetail")
	public ResponseVo reagentMethodDetail(Long topicTargetId,Long kitId,
										  @RequestParam(defaultValue = "false") boolean isGlobal,
										  @RequestHeader(name = StarterConstant.TOKEN) String token){
		Assert.isTrue(topicTargetId!=null && kitId!=null,"请求参数缺失!");
		MethodDetail reagentMethodDetail=topicLogic.getReagentMethodDetail(topicTargetId,kitId,isGlobal);
		return ResponseVo.success(reagentMethodDetail);
	}
	
	/**
	 * 添加历史数据
	 *
	 * @return
	 */
	@GetMapping("/addHistoryData")
	public ResponseVo addHistoryData(Long topicId,Long topicTargetId,
										  @RequestHeader(name = StarterConstant.TOKEN) String token){
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		Topic topic = topicService.selectById(topicId);
		Assert.isTrue(userInfo.getLabMemberId().equals(topic.getExecutorId()), "你没有权限操作该课题");
		List<TopicExperimentVo> list = topicLogic.addHistoryData(userInfo,topicTargetId);
		return ResponseVo.success(list);
	}
	
	/**
	 * 取消添加历史数据
	 *
	 * @return
	 */
	@GetMapping("/cancelHistoryData")
	public ResponseVo cancelHistoryData(Long topicId,Long topicTargetId,
			@RequestHeader(name = StarterConstant.TOKEN) String token){
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		Topic topic = topicService.selectById(topicId);
		Assert.isTrue(userInfo.getLabMemberId().equals(topic.getExecutorId()), "你没有权限操作该课题");
		topicLogic.cancelHistoryData(userInfo,topicTargetId);
		return ResponseVo.success();
	}
	
	/**
	 * 结束添加历史数据
	 *
	 * @return
	 */
	@GetMapping("/endHistoryData")
	public ResponseVo endHistoryData(Long topicId,Long topicTargetId,
			@RequestHeader(name = StarterConstant.TOKEN) String token){
		UserInfoVo userInfo = usersLogic.getUserByToken(token);
		Topic topic = topicService.selectById(topicId);
		Assert.isTrue(userInfo.getLabMemberId().equals(topic.getExecutorId()), "你没有权限操作该课题");
		topicLogic.endHistoryData(userInfo,topicTargetId);
		return ResponseVo.success();
	}
	
	
	/**
	 *根据ID获取实验目标信息
	 * 
	 * @return
	 */
	@GetMapping("/infoById")
	public ResponseVo topicExperimentInfo(@RequestParam Long topicExperimentId,
			@RequestHeader(name = StarterConstant.TOKEN) String token) {
		TopicExperiment topicExperiment = topicExperimentService.selectById(topicExperimentId);
		Assert.notNull(topicExperiment,"数据不存在");
		return ResponseVo.success(topicExperiment);
	}
	
}
